/*
 * PangoExample.cpp
 *
 *  Created on: 30/11/2009
 *      Author: luis
 */

#include "PangoWindow.h"

PangoWindow::PangoWindow(Circuito* circuito, std::string salida ) {
	int alto;
	int ancho;
	alto = (pow (2, circuito->get_lista_entradas().size()) + 2)*(TAMANIO_FILA+1);
	ancho = ((circuito->get_lista_entradas().size() + circuito->get_lista_salidas().size())*TAMANIO_COLUMNA)+DIVISION;

	//Defino la dimension de la ventana segun la dimension de la tabla
	set_size_request(ancho, alto);
	this->salida = salida;
    circuito_actual = circuito;
    division = 0;
    signal_expose_event().connect(sigc::mem_fun(*this,
    		&PangoWindow::onExposeEvent));
    timesnr_12 = new Pango::FontDescription("Times new roman Ultra-Light 12");
}


PangoWindow::~PangoWindow() {
    delete timesnr_12;
}

bool PangoWindow::onExposeEvent(GdkEventExpose *ev) {
	Cairo::RefPtr<Cairo::Context> cr =get_window()->create_cairo_context();

	pintar_nombre_entradas(cr);
	pintar_nombre_salidas(cr);
	pintar_combinacion_entradas(cr);
	pintar_combinacion_salidas(cr);
	pintar_lineas(cr);
    return true;
}

void PangoWindow::pintar_nombre_entradas(Cairo::RefPtr<Cairo::Context> cr){
	Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create (cr);
	std::list<Entrada*> lista_entradas = circuito_actual->get_lista_entradas();
	std::list<Entrada*>::iterator it = lista_entradas.end();
	int x = 3;
	int y = 2;
	unsigned int i;
	pangoLayout->set_font_description(*timesnr_12);
	std::string texto;
	texto = "ENTRADA";
	pangoLayout->set_text(texto);
	cr->move_to(x, y);
	pangoLayout->update_from_cairo_context(cr);
	pangoLayout->add_to_cairo_context(cr);
	texto.clear();
	y= y+TAMANIO_FILA;
	it--;

	/*
	 * Imprimo los nombres de las entradas en la posicion, en texto almaceno el nombre
	 */
	for (i=0; i<lista_entradas.size(); i++){
		texto.append((*it)->get_nombre());
		cr->move_to(x, y);
		pangoLayout->set_text(texto);
		pangoLayout->update_from_cairo_context(cr);
		pangoLayout->add_to_cairo_context(cr);
		x = x + TAMANIO_COLUMNA;
		texto.clear();
		it--;
	}
	division = x+DIVISION;
	cr->stroke();
}


void PangoWindow::pintar_nombre_salidas(Cairo::RefPtr<Cairo::Context> cr){
	Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create (cr);
	std::list<Salida*> lista_salidas = circuito_actual->get_lista_salidas();
	std::list<Salida*>::iterator it = lista_salidas.begin();
	int x = division;
	int y = 2;
	unsigned int i;
	pangoLayout->set_font_description(*timesnr_12);
	std::string texto;
	texto = "SALIDA";
	pangoLayout->set_text(texto);
	cr->move_to(x, y);
	pangoLayout->update_from_cairo_context(cr);
	pangoLayout->add_to_cairo_context(cr);

	texto.clear();
	y= y+TAMANIO_FILA;

	/*
	 * Imprimo los nombres de las salidas, en texto almaceno el nombre
	 */
	for (i=lista_salidas.size(); i>0; i--){
		texto.append((*it)->get_nombre());

		//Imprimo los nombres de las entradas
		cr->move_to(x, y);
		pangoLayout->set_text(texto);
		pangoLayout->update_from_cairo_context(cr);
		pangoLayout->add_to_cairo_context(cr);
		x = x + TAMANIO_COL_SALIDA;

		//Imprimo por cada nombre, las siglas T.T (tiempo transicion) para luego ubicarlas
		cr->move_to(x, y);
		pangoLayout->set_text("T.T.");
		pangoLayout->update_from_cairo_context(cr);
		pangoLayout->add_to_cairo_context(cr);
		x+= TAMANIO_COL_T_TRANS;
		texto.clear();
		it++;
	}
	cr->stroke();
}



void PangoWindow::pintar_combinacion_entradas(Cairo::RefPtr<Cairo::Context> cr){
	Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create (cr);
	int tamanio = circuito_actual->get_lista_entradas().size();
	int x = 3;
	int y = TAMANIO_FILA*2 + 2;
	int i, j;
	pangoLayout->set_font_description(*timesnr_12);
	std::string texto;
	int cantidad_combinaciones = pow(2, tamanio);
	for (i=0; i<cantidad_combinaciones; i++){
		texto = this->sumar_binario(i, tamanio);
		for (j=0; j<tamanio; j++){

			/*
			 * En out tomo el nro correspondiente (0 o 1) segun el numero binario actual que se obtuvo
			 * en el metodo sumar_binario
			 */

			char aux = texto[j];
			std::string out;
			out += aux;

			//Pinto los binarios que son la combinacion de las entradas
			cr->move_to(x, y);
			pangoLayout->set_text(out);
			pangoLayout->update_from_cairo_context(cr);
			pangoLayout->add_to_cairo_context(cr);
			x=x+TAMANIO_COLUMNA;
		}
		texto.clear();
		x=3;
		y=y+TAMANIO_FILA;
	}
	cr->stroke();
}


void PangoWindow::pintar_combinacion_salidas(Cairo::RefPtr<Cairo::Context> cr){
	Glib::RefPtr<Pango::Layout> pangoLayout = Pango::Layout::create (cr);
	int tamanio = circuito_actual->get_lista_salidas().size();
	int x = division;
	int y = TAMANIO_FILA*2 +2;
	unsigned int i;
	int k=0;
	unsigned int limite = pow (2,circuito_actual->get_lista_entradas().size())*circuito_actual->get_lista_salidas().size();
	for (i=0; i<limite; i++){

		//Parseo la salida que se pasa por parametro para intar la combinacion de salidas
		char valor = salida[k];
		std::string out;
		out += valor;

		//Pinto la combinacion de salidas
		cr->move_to(x, y);
		pangoLayout->set_text(out);
		pangoLayout->update_from_cairo_context(cr);
		pangoLayout->add_to_cairo_context(cr);

		std::string auxiliar;
		k++;
		while(salida[k]!='|'){
			auxiliar+=salida[k];
			k++;
		}

		//Pinto el tiempo de transicion
		cr->move_to(x+TAMANIO_COL_SALIDA, y);
		pangoLayout->set_text(auxiliar);
		pangoLayout->update_from_cairo_context(cr);
		pangoLayout->add_to_cairo_context(cr);


		if ((i+1)%tamanio==0){
			x = division;
			y += TAMANIO_FILA;
		}
		else
			x += TAMANIO_COLUMNA;
		k++;
	}
	cr->stroke();
}


void PangoWindow::pintar_lineas(Cairo::RefPtr<Cairo::Context> cr){
	cr->move_to(0, 0);
	int hasta;
	hasta = circuito_actual->get_lista_entradas().size()*TAMANIO_COLUMNA +
			circuito_actual->get_lista_salidas().size()*TAMANIO_COLUMNA+ DIVISION;
	int i;
	cr->set_line_width(2);
	cr->set_source_rgb(1,0,0);

	//Pinto las lineas horizontales
	for (i=0; i<(pow(2, circuito_actual->get_lista_entradas().size()))+3; i++){
		cr->move_to(0, (i*TAMANIO_FILA)+1);
		cr->line_to(hasta, (i*TAMANIO_FILA)+1);
	}

	//Pinto las lineas verticales
	cr->stroke();
	cr->move_to(0,0);
	cr->line_to(0, (pow(2, circuito_actual->get_lista_entradas().size()))*TAMANIO_FILA + TAMANIO_FILA*2);
	cr->move_to(circuito_actual->get_lista_entradas().size()*TAMANIO_COLUMNA + DIVISION/2, 0);
	cr->line_to(circuito_actual->get_lista_entradas().size()*TAMANIO_COLUMNA + DIVISION/2,
			(pow(2, circuito_actual->get_lista_entradas().size()))*TAMANIO_FILA + TAMANIO_FILA*2);
	cr->move_to(circuito_actual->get_lista_entradas().size()*TAMANIO_COLUMNA + DIVISION +
			circuito_actual->get_lista_salidas().size()*TAMANIO_COLUMNA, 0);
	cr->line_to(circuito_actual->get_lista_entradas().size()*TAMANIO_COLUMNA + DIVISION +
			circuito_actual->get_lista_salidas().size()*TAMANIO_COLUMNA,
			(pow(2, circuito_actual->get_lista_entradas().size()))*TAMANIO_FILA + TAMANIO_FILA*2);
	cr->stroke();
}


void PangoWindow::pintar_en_ventana(Cairo::RefPtr<Cairo::Context> cr){

	pintar_nombre_entradas(cr);
	pintar_nombre_salidas(cr);
	pintar_combinacion_entradas(cr);
	pintar_combinacion_salidas(cr);
	pintar_lineas(cr);


}

std::string PangoWindow::sumar_binario(int iteracion, unsigned int cantidad){
	std::string aux;
	int dig;
	while((iteracion)>=2){
		dig=iteracion%2;
		aux.push_back((char)(dig+48));
		iteracion=iteracion/2;
	}
	aux.push_back((char)(iteracion+48));
	std::string otro;

	int i;
	unsigned int j;
	for (j=0; (j<cantidad-aux.length());j++){
		otro.push_back('0');
	}
	for (i=aux.length()-1; i>=0; i--){
		otro.push_back(aux[i]);
	}
	return otro;
}

